#include <iostream>
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <cstdio>
#include <assert.h>
using namespace std;

#define THREAD_NUM 5

int tickets = 3000;

class Thread_Date
{
public:
    Thread_Date(const string n, pthread_mutex_t *m)
        : mtx(m), name(n)
    {
    }
    pthread_mutex_t *mtx;
    string name;
};

void *getTickets(void *args)
{
    Thread_Date *td = (Thread_Date *)args;
    while (1)
    {
        // usleep(1000);
        int n = pthread_mutex_lock(td->mtx);
        assert(n == 0);
        if (tickets > 0)
        {
            printf("%s %d\n", td->name.c_str(), tickets);
            tickets--;
            n = pthread_mutex_unlock(td->mtx);
            assert(n == 0);
        }
        else
        {
            n = pthread_mutex_unlock(td->mtx);
            assert(n == 0);

            break;
        }
        delete td;
    }
    cout << td->name << "is quit" << endl;
    // pthread_exit((void*)3);
    usleep(10000);
    return nullptr;
}

int main()
{
    pthread_mutex_t mutex;
    pthread_mutex_init(&mutex, nullptr);
    pthread_t tid[THREAD_NUM];

    for (int i = 0; i < THREAD_NUM; i++)
    {
        string name = "thread: ";
        name += to_string(i + 1);

        Thread_Date *td = new Thread_Date(name, &mutex);
        pthread_create(tid + i, nullptr, getTickets, (void *)td);

    }
    for (int i = 0; i < THREAD_NUM; i++)
    {
        pthread_join(tid[i], nullptr);
    }
    pthread_mutex_destroy(&mutex);

    // pthread_create(&tid1, nullptr, getTickets, (void*)"thread one:");
    // pthread_create(&tid2, nullptr, getTickets, (void*)"thread two:");
    // pthread_create(&tid2, nullptr, getTickets, (void*)"thread three:");

    // pthread_join(tid1, nullptr);
    // pthread_join(tid2, nullptr);
    // pthread_join(tid3, nullptr);

    return 0;
}